#pragma once
/**
 * 文件版 model
*/
#include <iostream>
#include <unordered_map>
#include <fstream>
#include <vector>
#include <cassert>
#include "../comm/util.hpp"
#include "../comm/Log.hpp"
#include <mysql/mysql.h>
namespace ns_model
{
    using namespace ns_util;
    using namespace ns_log;

    struct  Question
    {
        std::string number;//提号
        std::string title;//题目名
        std::string star;//难易
        int cpu_limit;//时间限制
        int mem_limit;//空间限制
        std::string desc;//题目描述
        std::string header;//预制代码
        std::string tail;//测试代码
    };
    

    /**
     * 接口和文件版的保持一致，这样就不用去修改其他的头文件
     * 并且其中同样是通过model和底层数据进行一个交互
     * 最终将数据存放到 Question 结构中！
    */
    const std::string filename = "oj_question ";
    const char* host = "127.0.0.1";
    const char* user = "oj_mysql";
    const char* passwd = "root123Zyk@1";
    const char* db = "oj";
    const int port = 3306;
    
    

    class Model
    {
    private:
       
    public:
        Model(){}
        ~Model(){}
       
       // vector中存的是一行行的题目Question
        bool Mysql_Query(const std::string& sql,std::vector<Question>* out){

            MYSQL* my = mysql_init(nullptr);//1. 初始化数据库
            //连接数据库，失败返回nullptr
            if(mysql_real_connect(my,host,user,passwd,db,port,nullptr,0) == nullptr){
                LOG(FATAL) << "连接数据库失败！" << "\n";
                return false;
            }
            // 一定要设置该链接的编码格式, 要不然会出现乱码问题
            mysql_set_character_set(my, "utf8");
            LOG(INFO) << "连接数据库成功！" << sql << "\n";

            //调用query接口，返回值不等与0 代表失败
            if(mysql_query(my,sql.c_str()) != 0){
                LOG(WARNING) << sql << "execute error" << "\n";
                return false;
            }

            //分析结果(处理查询语句)
            MYSQL_RES* res = mysql_store_result(my);//获取my中的结果集
            
            //获取行数 和 列数
            int rows = mysql_num_rows(res);
            int colos = mysql_num_fields(res);

            Question q;
            for(int i = 0; i < rows ;i++){
                //获取某行数据，因为一行只有一个数据 所以直接取 0 即可
                MYSQL_ROW row = mysql_fetch_row(res);//mysql_fetch_row会像一个迭代器一样自动遍历
                
                //mysql_row  的类型本质就是一个 char**
                q.number = row[0];
                q.title = row[1];
                q.star = row[2];
                q.desc = row[3];
                q.header = row[4];
                q.tail = row[5];
                q.cpu_limit = atoi(row[6]);//row[6]是字符串 char* 所以需要强转一下
                q.mem_limit = atoi(row[7]);

                out->push_back(q);
            }
            

            mysql_free_result(res);//注意释放 RES 结果集

            mysql_close(my);//关闭数据库

            return true;
        }

        //获取所有题目
        bool GetAllQuestions(std::vector<Question>* out)
        {
            //创建查询的sql
            std::string sql = "select * from ";
            sql += filename;

            return Mysql_Query(sql,out);
        }
        //获得某一题
        bool GetOneQuestion(const std::string& number,Question* out)
        {
           //查询某一道题的sql
            std::string sql = "select * from ";
            sql += filename + "where number = ";
            sql += "\'" + number + "\'";

            bool ret = false;   
            std::vector<Question> result;
            Mysql_Query(sql,&result);
            if(result.size() == 1){
                *out = result[0];
                ret = true;
            }
            else{
                LOG(FATAL) << "获取某一题失败，sql为：" << sql << "\n";
            }
            return ret;
        }
    };
}